using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace MefBasic.Data
{
    [Serializable]
    public class ChangedDataCollection
    {
        public ChangedDataCollection()
        {
            Items=new Dictionary<string, List<object>>();
        }
        public Dictionary<string, List<object>> Items { get; set; }

        public void Add<T>(T data)
        {
            Add(data, typeof(T).ToString());
        }

        public void Add(object data, string key)
        {
            var collection = GetDataCollection(key);
            if (collection.Contains(data) == false)
                collection.Add(data);
        }

        private List<object> GetDataCollection(string key)
        {
            List<object> dataCollection;
            if(Items.ContainsKey(key))
            {
                dataCollection = Items[key];
            }
            else
            {
                dataCollection=new List<object>();
                Items.Add(key,dataCollection);
            }
            return dataCollection;
        }

        public T GetObject<T>()
        {
            return (T) GetObject(typeof (T).ToString());
        }

        public T[] GetObjects<T>()
        {
            var key = typeof(T).ToString();
            return GetObjects<T>(key);
        }

        public T[] GetObjects<T>(string key)
        {
            var objs = GetDataCollection(key).ToArray();
            var objects=new List<T>();
            foreach (var o in objs)
            {
                objects.Add((T) o);
            }
            return objects.ToArray();
        }
        public T[] OfType<T>()
        {
            var items = new List<T>();
            foreach (var list in Items.Values)
            {
                items.AddRange(list.OfType<T>());
            }
            return items.ToArray();
        }

        public object GetObject(string key)
        {
            return GetDataCollection(key).SingleOrDefault();
        }

        public void AddRange<T>(IEnumerable list)
        {
            foreach (T item in list)
            {
                Add(item);
            }
        }

        public void Remove<T>(T data)
        {
            GetDataCollection(typeof (T).ToString()).Remove(data);
        }

        public void Clear()
        {
            Items.Clear();
        }
        public bool Contains<T>(T data)
        {
            var collection = GetDataCollection(typeof(T).ToString());
            return collection.Contains(data);
        }

        public T GetObject<T>(string key)
        {
            var value = GetObject(key);
            if (value == null)
                return default(T);
            return (T)value;
        }

        public bool ContainsKey<T>()
        {
            return ContainsKey(typeof(T).ToString());
        }
        public bool ContainsKey(string key)
        {
            return Items.ContainsKey(key);
        }

        public bool Contains<T>()
        {
            return GetDataCollection(typeof (T).ToString()).Count > 0;
        }

        public void Remove<T>()
        {
            GetDataCollection(typeof (T).ToString()).Clear();
        }
    }
}